import { PlaceUseLog } from './../domain/models/placeUseLog';
import { IQueryObject } from 'tiny-entity2/queryObject';
import { Transaction } from "tiny-entity2";
import { ApiDataContext } from "../domain/apiDataContext";
import { Place } from "../domain/models/place";
import { PlaceType } from "../domain/models/placeType";
import { BaseService } from "./baseService";

export class PlaceService extends BaseService {
    DeletePlaceById(id: string, ctx?: ApiDataContext) {
        ctx || (ctx = new ApiDataContext());
        return Transaction(ctx, async (ctx) => {
            await ctx.Delete(x => x.id == $args1, ctx.Place, { $args1: id });
        });
    }
    DeletePlaceUseLog(id: string, ctx?: ApiDataContext) {
        ctx || (ctx = new ApiDataContext());
        return Transaction(ctx, async (ctx) => {
            await ctx.Delete(x => x.id == $args1, ctx.PlaceUseLog, { $args1: id });
        });
    }
    CreatePlace(entity: Place, ctx?: ApiDataContext) {
        ctx || (ctx = new ApiDataContext());
        return Transaction(ctx, async (ctx) => {
            let d = new Place();
            d.ConverToEntity(entity);
            return ctx.Create(d);
        });
    }
    UpdatePlace(entity: Place, ctx?: ApiDataContext) {
        ctx || (ctx = new ApiDataContext());
        return Transaction(ctx, async (ctx) => {
            let d = new Place();
            d.ConverToEntity(entity);
            return ctx.Update(d);
        });
    }
    async GetPlaceById(id: string) {
        let ctx = new ApiDataContext();
        let place = await ctx.Place.First(x => x.id == $args1, { $args1: id });

        const nowTs = Date.now();
        place.placeUseLogs = await ctx.PlaceUseLog.Where(x => x.endTime >= $args1 && x.placeId == $args2, { $args1: nowTs, $args2: id }).ToList();

        return place;
    }

    async QueryPlaceUseLogs(params: PlaceUseLogQueryParams) {
        let ctx = new ApiDataContext();
        let q = ctx.PlaceUseLog as IQueryObject<PlaceUseLog>;
        if (params) {
            if (params.placeId) {
                q = q.Where(x => x.placeId == $args1, { $args1: params.placeId });
            }
            if (params.dataRegisterId) {
                q = q.Where(x => x.dataRegisterId == $args1, { $args1: params.dataRegisterId });
            }
            if (params.useObjectId) {
                q = q.Where(x => x.useObjectId == $args1, { $args1: params.useObjectId });
            }
            if (params.useObjectType) {
                q = q.Where(x => x.useObjectType == $args1, { $args1: params.useObjectType });
            }
            if (params.placeTypeId) {
                q = q.Where(x => x.placeTypeId == $args1, { $args1: params.placeTypeId });
            }
            if (params.endTimeBegin) {
                q = q.Where(x => x.endTime >= $args1, { $args1: params.endTimeBegin });
            }
            else if (params.endTimeEnd) {
                q = q.Where(x => x.endTime < $args1, { $args1: params.endTimeEnd });
            }
            else {
                const nowTs = Date.now();
                q = q.Where(x => x.endTime >= $args1, { $args1: nowTs });
            }

        }

        return q.OrderBy(x => x.beginTime).ToList();
    }

    async QueryPlace(params: PlaceQueryParams) {
        let ctx = new ApiDataContext();
        let q = ctx.Place as IQueryObject<Place>;
        if (params) {
            if (params.placeTypeId) {
                q = q.Where(x => x.placeTypeId == $args1, { $args1: params.placeTypeId });
            }
            if (params.orgId) {
                q = q.Where(x => x.orgId == $args1, { $args1: params.orgId });
            }
        }

        let result = await q.ToList();
        if (result.length > 0) {
            const placeUseLogs = await ctx.PlaceUseLog.Where(x => x.endTime >= $args1, { $args1: Date.now() }).Contains(x => x.placeId, result.map(x => x.id)).ToList();
            result.forEach(item => {
                item.placeUseLogs = placeUseLogs.filter(x => x.placeId == item.id);
            });
        }

        return result;
    }

    CreatePlaceType(entity: PlaceType, ctx?: ApiDataContext) {
        ctx || (ctx = new ApiDataContext());
        return Transaction(ctx, async (ctx) => {
            let d = new PlaceType();
            d.ConverToEntity(entity);
            return ctx.Create(d);
        });
    }
    UpdatePlaceType(entity: PlaceType, ctx?: ApiDataContext) {
        ctx || (ctx = new ApiDataContext());
        return Transaction(ctx, async (ctx) => {
            let d = new PlaceType();
            d.ConverToEntity(entity);
            return ctx.Update(d);
        });
    }
    GetPlaceTypeById(id: string) {
        let ctx = new ApiDataContext();
    }
    QueryPlaceType(params: PlaceTypeQueryParams) {
        let ctx = new ApiDataContext();
        let q = ctx.PlaceType as IQueryObject<PlaceType>;
        if (params) {
            if (params.orgId) {
                q = q.Where(x => x.orgId == $args1, { $args1: params.orgId });
            }
            if (params.name) { }
        }

        return q.ToList();
    }
    DeletePlaceTypeById(id: any, ctx?: ApiDataContext) {
        ctx || (ctx = new ApiDataContext());
        return Transaction(ctx, async (ctx) => {
            await ctx.Delete(x => x.id == $args1, ctx.PlaceType, { $args1: id });
            await ctx.Delete(x => x.placeTypeId == $args1, ctx.Place, { $args1: id });
        });
    }

    CreatePlaceUseLog(entity: PlaceUseLog, ctx?: ApiDataContext) {
        ctx || (ctx = new ApiDataContext());
        return Transaction(ctx, async (ctx) => {
            let d = new PlaceUseLog();
            d.ConverToEntity(entity);
            return ctx.Create(d);
        });
    }
}

export interface PlaceTypeQueryParams {
    orgId?: string;
    name?: string;
}

export interface PlaceQueryParams {
    orgId?: string;
    placeTypeId?: string;
    searchBeginTime?: number;
    searchEndTime?: number;
}

export interface PlaceUseLogQueryParams {
    orgId?: string;
    placeId?: string;
    useObjectId?: string;
    useObjectType?: string;
    beginTime?: number;
    endTimeBegin?: number;
    endTimeEnd?: number;
    placeTypeId?: string;
    dataRegisterId?: string;
}